<?php

namespace App\Http\Requests\Account\Attendance;

use Carbon\Carbon;
use App\Models\User;
use Illuminate\Validation\Rule;
use App\Package\Attendance\Time;
use App\Exceptions\GeneralException;
use Illuminate\Foundation\Http\FormRequest;

/**
 * 用户打卡请求逻辑
 *
 * Date: 17/04/2018
 * @author George
 * @package App\Http\Requests\Account\Attendance
 */
class SigninRequest extends FormRequest
{
	/**
	 * 用户授权
	 *
	 * Date: 17/04/2018
	 * @author George
	 * @return bool
	 * @throws GeneralException
	 */
    public function authorize()
    {
        $now = Carbon::now();
        /**
         * @var User $user
         */
        $user = $this->user();
        $projects = $user->getProjects();

		if (! $user->hasCompany()) {
			throw new GeneralException('您没有加入公司，无法签到', 403);
		}

		// 判断用户是否拥有项目
		if ($projects->isEmpty()) {
			throw new GeneralException('您没有加入项目，无法签到', 403);
		}

		// 判断用户是否有排班
		if ($schedule = $user->getSchedule($this->get('type'))) {
			$this->offsetSet('schedule_id', $schedule->id);
		} else {
			throw new GeneralException('今天您没有排班，无法签到', 403);
		}

		// 判断打卡类型
		if ($this->get('type') === 'checkin') {
			// 判断当天的排班是否已存在签到记录，如果有则抛出异常
		    if ($schedule->attendance) {
                throw new GeneralException('您今天已经签到，无法再次签到', 403);
            }

            // 判断用户是否拥有指定项目
            if ($projects->contains($schedule->project_id)) {
                $attributes = [
                    'user_id' => $user->id,
                    'project_id' => $schedule->project_id,
                    'company_id' => $user->company_id,
                    'schedule_id' => $schedule->id,
                    'genre_id' => $schedule->genre_id,
                    'genre_name' => $schedule->genre_name,
                    'checkin_time' => $now->toDateTimeString(),
					'checkin_status' => Time::check($schedule, $now->toDateTimeString(), $this->get('type')),
                    'checkin_longitude' => $this->get('longitude'),
                    'checkin_latitude' => $this->get('latitude'),
                    'checkin_address' => $this->get('address'),
                    'checkin_example' => $this->get('example'),
                    'checkin_image' => $this->get('selfie')
                ];
                // 替换掉用户输入的表单内容
                $this->replace($attributes);
            }
        } else {
            $attendance = optional($schedule)->attendance;
            // 判断是否已经签到
            if ($attendance) {
                // 判断是否可签退
                if (Carbon::parse($schedule->end)->gt(Carbon::now())) {
                    throw new GeneralException('未到下班时间无法签退', 403);
                }
            } else {
                throw new GeneralException('您还未签到，请先签到', 403);
            }
            $attributes = [
                'checkout_longitude' => $this->get('longitude'),
                'checkout_latitude' => $this->get('latitude'),
				'checkout_address' => $this->get('address'),
                'checkout_example' => $this->get('example'),
                'checkout_image' => $this->get('selfie'),
                'checkout_time' => $now->toDateTimeString(),
                'checkout_status' => Time::check($schedule, $now->toDateTimeString(), $this->get('type')),
                'attendance' => $attendance
            ];
            // 替换掉用户输入的表单内容
            $this->replace($attributes);
        }
        // 移除Type 字段
        $this->offsetUnset('type');
        return true;
    }

	/**
	 * 定义表单验证规则
	 *
	 * Date: 17/04/2018
	 * @author George
	 * @return array
	 */
    public function rules()
    {
        return [
			'longitude' => ['required', 'regex:/^[\-\+]?(0?\d{1,2}\.\d{1,5}|1[0-7]?\d{1}\.\d{1,6}|180\.0{1,6})$/'],
			'latitude' => ['required', 'regex:/^[\-\+]?([0-8]?\d{1}\.\d{1,6}|90\.0{1,6})$/'],
			'address' => 'required',
			'example' => 'required',
			'selfie' => 'required',
            'type' => ['required', Rule::in(['checkin', 'checkout'])]
        ];
    }

	/**
	 * 定义错误消息
	 *
	 * Date: 16/04/2018
	 * @author George
	 * @return array
	 */
	public function messages()
	{
		return [
			'longitude.required' => '请提供签到的经度',
			'longitude.regex' => '签到的经度无效',
			'latitude.required' => '请提供签到的纬度',
			'latitude.regex' => '签到的纬度无效',
			'address.required' => '未获取到地址信息',
			'example.required' => '示例图片无效',
			'selfie.required' => '请选择签到的项目',
			'type.required' => '请选择打卡类型',
			'type.in' => '打卡类型错误',
		];
	}
}
